package cn.xinfei.xdecision.common.utils.util;

import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @author zdy
 * @since 2023-03-20
 */
@Slf4j
public class FutureUtils {

    private FutureUtils() {
    }

    public static <T> void futureGet(Future<T> future, ErrorCodeEnum errorCodeEnum) {
        futureGet(future, errorCodeEnum.getCode(), errorCodeEnum.getMessage());
    }

    /**
     * 等待此future完成，然后返回其结果
     *
     * @param <T>       the future return type
     * @param future    future
     * @param errorCode 异常信息
     */
    public static <T> void futureGet(Future<T> future, String errorCode, String msg) {
        try {
            future.get();
        } catch (ApiException apiException) {
            log.error("内部异常", apiException);
            throw new ApiException(errorCode, msg);
        } catch (InterruptedException interruptedException) {
            Thread.currentThread().interrupt();
            if (log.isErrorEnabled()) {
                log.error("futureGet 线程中断", interruptedException);
            }
            throw new ApiException(errorCode, interruptedException.getMessage());
        } catch (ExecutionException executionException) {
            if (log.isErrorEnabled()) {
                log.error("futureGet 业务异常 异常 = {}", executionException.getMessage(), executionException);
            }
            throw new ApiException(errorCode, executionException.getMessage());
        } catch (CancellationException cancellationException) {
            if (log.isErrorEnabled()) {
                log.error("this future was cancelled");
            }
            throw new ApiException(errorCode, cancellationException.getMessage());
        }
    }

    /**
     * 等待此future完成，然后返回其结果
     *
     * @param <T>       the future return type
     * @param future    future
     * @param errorCode 异常信息
     */
    public static <T> T futureGet(Future<T> future, String errorCode, String msg, long timeout, TimeUnit unit) {
        try {
            return future.get(timeout, unit);
        } catch (ApiException apiException) {
            log.error("内部异常", apiException);
            throw new ApiException(errorCode, msg);
        } catch (InterruptedException interruptedException) {
            Thread.currentThread().interrupt();
            if (log.isErrorEnabled()) {
                log.error("futureGet 线程中断", interruptedException);
            }
            throw new ApiException(errorCode, interruptedException.getMessage());
        } catch (ExecutionException executionException) {
            if (log.isErrorEnabled()) {
                log.error("futureGet 业务异常 异常 = {}", executionException.getMessage(), executionException);
            }
            throw new ApiException(errorCode, executionException.getMessage());
        } catch (CancellationException | TimeoutException cancellationException) {
            if (log.isErrorEnabled()) {
                log.error("this future was cancelled");
            }
            throw new ApiException(errorCode, cancellationException.getMessage());
        }
    }
}
